# ~*~ coding: utf-8 ~*~
import json

from apps.ops.ansible.inventory import BaseInventory
from apps.extensions import db
from apps.tasks.models import InventoryGroupHost, InventoryHostVariable
from apps.assets.models import Asset
from apps.assets.utils.ansible import db_to_ansible_of_asset_admin_users


class BeesInventory(BaseInventory):
    def __init__(self, hosts, run_as, become, run_as_admin=True):
        """
        :param hosts:   [
            {"hostname":"testserver", "ip": 192.169.1.111},
            {"hostname":"testserver2", "ip": 192.169.1.222},
        ]
        :param run_as: 远程服务器连接信息  <远程服务器的普通用户的用户名和密码>
        [
            {   "username": "sa",
                "password": "123456",
                "private_key": "/tmp/private_key",
            },
            {   "username": "dev",
                "password": "654321",
                "private_key": "/tmp/private_key",
            }
        ]
        :param become: 连接远程服务器后, 执行命令的权限 <远程服务器的管理员的用户名和密码>
         [
            {
                "method": "sudo",
                "user": "root",
                "pass": "",
            },
            {
                "method": "sudo",
                "user": "root",
                "pass": "",
            }
        ]
        :param run_as_admin: 是否需要使用sudo运行ansible
        """

        self._hosts = hosts
        self._run_as = run_as
        self._become = become
        self._run_as_admin = run_as_admin

        host_list = self.convert_to_ansible()
        super().__init__(host_list=host_list, group_list=None)

    def convert_to_ansible(self):
        host_list = []
        for i in range(len(self._hosts)):
            host_info = {}
            host_info.update(self._hosts[i])
            host_info.update(self._run_as[i])
            if self._run_as_admin:
                host_info['become'] = self._become[i]
            host_list.append(host_info)
        return host_list


class BeesCustomInventory(BaseInventory):

    def __init__(self, hosts=None, groups=None):
        """
        :param hosts:   Model Asset object
        :param groups:  Model InventoryGroup object
        """
        # self.all_hosts = hosts or []
        # self.all_groups = groups or []

        # 游离态的对象和持久态对象无法直接对比是否相等
        self.all_hosts = [db.session.merge(h) for h in hosts]
        self.all_groups = [db.session.merge(g) for g in groups]

        # {
        #     "host_id": ["group1", "group2"],
        #     "host_id": ["group1"],
        # }
        self.host_groups = {}

        group_list = self.ansible_groups()
        # print('groups --->{}'.format(group_list))
        host_list = self.ansible_hosts()
        # print('hosts  --->{}'.format(host_list))
        super().__init__(host_list=host_list, group_list=group_list)

    def ansible_groups(self):
        groups = []
        for g in self.all_groups:
            assets = db.session.query(Asset). \
                join(InventoryGroupHost, Asset.id == InventoryGroupHost.asset_id). \
                filter(InventoryGroupHost.group_id == g.id). \
                all()

            # self.hosts.extend(assets)
            for asset in assets:
                # 将组内主机添加到所有主机中
                if asset not in self.all_hosts:
                    self.all_hosts.append(asset)

                # 对主机进行分组
                if asset.id not in self.host_groups.keys():
                    self.host_groups[asset.id] = [g.name]
                else:
                    self.host_groups[asset.id].append(g.name)

            groups.append(
                {
                    "name": g.name,
                    "children": [asset.hostname for asset in assets],
                    "vars": g.vars
                }
            )
        return groups

    def ansible_hosts(self):
        # 获取基本信息
        hosts = []
        _hosts, _run_as, _become = db_to_ansible_of_asset_admin_users(self.all_hosts)

        # 获取vars信息
        hids = [h.id for h in self.all_hosts]
        variables = db.session.query(InventoryHostVariable). \
            filter(InventoryHostVariable.asset_id.in_(hids)).\
            all()
        var_dict = {}
        for v in variables:
            var_dict[v.asset_id] = v.vars

        # 将信息合并到hosts中
        for i in range(len(self.all_hosts)):
            host_info = {}
            host_info.update(_hosts[i])
            host_info.update(_run_as[i])

            host_info['become'] = _become[i]
            host_info["vars"] = var_dict.get(_hosts[i].get('id')) or {}
            host_info["groups"] = self.host_groups.get(_hosts[i].get('id')) or []

            hosts.append(host_info)
        return hosts
